﻿<script language="javascript">
/**
 * @see http://www.movable-type.co.uk/scripts/aes.html
 */
var AESClass = function()
{
    var Sbox =  [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
                 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
                 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
                 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
                 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
                 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
                 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
                 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
                 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
                 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
                 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
                 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
                 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
                 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
                 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
                 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
    var Rcon = [ [0x00, 0x00, 0x00, 0x00],
                 [0x01, 0x00, 0x00, 0x00],
                 [0x02, 0x00, 0x00, 0x00],
                 [0x04, 0x00, 0x00, 0x00],
                 [0x08, 0x00, 0x00, 0x00],
                 [0x10, 0x00, 0x00, 0x00],
                 [0x20, 0x00, 0x00, 0x00],
                 [0x40, 0x00, 0x00, 0x00],
                 [0x80, 0x00, 0x00, 0x00],
                 [0x1b, 0x00, 0x00, 0x00],
                 [0x36, 0x00, 0x00, 0x00] ];
    
    function Cipher(input, w) {
      var Nb = 4;
      var Nr = w.length/Nb - 1;
      var state = [[],[],[],[]];
      for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
      state = AddRoundKey(state, w, 0, Nb);
      for (var round=1; round<Nr; round++) {
        state = SubBytes(state, Nb);
        state = ShiftRows(state, Nb);
        state = MixColumns(state, Nb);
        state = AddRoundKey(state, w, round, Nb);
      }
      state = SubBytes(state, Nb);
      state = ShiftRows(state, Nb);
      state = AddRoundKey(state, w, Nr, Nb);
      var output = new Array(4*Nb);
      for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
      return output;
    }
    
    function SubBytes(s, Nb) {
      for (var r=0; r<4; r++) {
        for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
      }
      return s;
    }
    
    function ShiftRows(s, Nb) { 
      var t = new Array(4);
      for (var r=1; r<4; r++) {
        for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];
        for (var c=0; c<4; c++) s[r][c] = t[c];
      }
      return s;
    }
    
    function MixColumns(s, Nb) {
      for (var c=0; c<4; c++) {
        var a = new Array(4);
        var b = new Array(4);
        for (var i=0; i<4; i++) {
          a[i] = s[i][c];
          b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
        }
        s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3];
        s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3];
        s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3];
        s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3];
      }
      return s;
    }
    
    function AddRoundKey(state, w, rnd, Nb) {
      for (var r=0; r<4; r++) {
        for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
      }
      return state;
    }
    
    function KeyExpansion(key) {
      var Nb = 4;
      var Nk = key.length/4
      var Nr = Nk + 6;
      var w = new Array(Nb*(Nr+1));
      var temp = new Array(4);
      for (var i=0; i<Nk; i++) {
        var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
        w[i] = r;
      }
      for (var i=Nk; i<(Nb*(Nr+1)); i++) {
        w[i] = new Array(4);
        for (var t=0; t<4; t++) temp[t] = w[i-1][t];
        if (i % Nk == 0) {
          temp = SubWord(RotWord(temp));
          for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
        } else if (Nk > 6 && i%Nk == 4) {
          temp = SubWord(temp);
        }
        for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
      }
      return w;
    }
    
    function SubWord(w) {
      for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
      return w;
    }
    
    function RotWord(w) {
      w[4] = w[0];
      for (var i=0; i<4; i++) w[i] = w[i+1];
      return w;
    }
    
    function escCtrlChars(str) {
      return str.replace(/[\0\t\n\v\f\r\xa0'"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
    }
    function unescCtrlChars(str) {
      return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
    }
    
    function AESEncryptCtr(plaintext, password, nBits) {
      if(nBits == null) nBits = 256;
      if (!(nBits==128 || nBits==192 || nBits==256)) return '';
    
      var nBytes = nBits/8;
      var pwBytes = new Array(nBytes);
      for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
      var key = Cipher(pwBytes, KeyExpansion(pwBytes));
      key = key.concat(key.slice(0, nBytes-16));
      var blockSize = 16;
      var counterBlock = new Array(blockSize);
      var nonce = (new Date()).getTime();
      for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
      for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
      var keySchedule = KeyExpansion(key);
      var blockCount = Math.ceil(plaintext.length/blockSize);
      var ciphertext = new Array(blockCount);
      
      for (var b=0; b<blockCount; b++) {
        for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
        for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
        var cipherCntr = Cipher(counterBlock, keySchedule);
        
        var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
        var ct = '';
        for (var i=0; i<blockLength; i++) {
          var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
          var cipherByte = plaintextByte ^ cipherCntr[i];
          ct += String.fromCharCode(cipherByte);
        }
        ciphertext[b] = escCtrlChars(ct);
      }
      var ctrTxt = '';
      for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
      ctrTxt = escCtrlChars(ctrTxt);
      return ctrTxt + '-' + ciphertext.join('-');
    }
    
    function AESDecryptCtr(ciphertext, password, nBits) {
      if(nBits == null) nBits = 256;
      if (!(nBits==128 || nBits==192 || nBits==256)) return '';
      var nBytes = nBits/8;
      var pwBytes = new Array(nBytes);
      for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
      var pwKeySchedule = KeyExpansion(pwBytes);
      var key = Cipher(pwBytes, pwKeySchedule);
      key = key.concat(key.slice(0, nBytes-16));
      var keySchedule = KeyExpansion(key);
      ciphertext = ciphertext.split('-');
      var blockSize = 16;
      var counterBlock = new Array(blockSize);
      var ctrTxt = unescCtrlChars(ciphertext[0]);
      for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
      var plaintext = new Array(ciphertext.length-1);
      for (var b=1; b<ciphertext.length; b++) {
        for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
        for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
        var cipherCntr = Cipher(counterBlock, keySchedule);
        ciphertext[b] = unescCtrlChars(ciphertext[b]);
        var pt = '';
        for (var i=0; i<ciphertext[b].length; i++) {
          var ciphertextByte = ciphertext[b].charCodeAt(i);
          var plaintextByte = ciphertextByte ^ cipherCntr[i];
          pt += String.fromCharCode(plaintextByte);
        }
        plaintext[b-1] = pt;
      }
      return plaintext.join('');
    }
    // public
    this.encrypt = AESEncryptCtr;
    this.decrypt = AESDecryptCtr;
}
/**
UTF8(BOM)  LGPL  trydofor.com  Mar. 2008
===========================================================
* @see http://www.movable-type.co.uk/scripts/aes.html
*/

var B64Class = function()
{
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
    function encodeBase64(str) {
       var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
       
       str = utf16to8(str);
    
       do {
          o1 = str.charCodeAt(i++);
          o2 = str.charCodeAt(i++);
          o3 = str.charCodeAt(i++);
          
          bits = o1<<16 | o2<<8 | o3;
          
          h1 = bits>>18 & 0x3f;
          h2 = bits>>12 & 0x3f;
          h3 = bits>>6 & 0x3f;
          h4 = bits & 0x3f;
          
          if (isNaN(o3)) h4 = 64;
          if (isNaN(o2)) h3 = 64;
          
          enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
       } while (i < str.length);
       
       return enc;
    }
    
    function decodeBase64(str) {
       var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
    
       do {
          h1 = b64.indexOf(str.charAt(i++));
          h2 = b64.indexOf(str.charAt(i++));
          h3 = b64.indexOf(str.charAt(i++));
          h4 = b64.indexOf(str.charAt(i++));
          
          bits = h1<<18 | h2<<12 | h3<<6 | h4;
          
          o1 = bits>>16 & 0xff;
          o2 = bits>>8 & 0xff;
          o3 = bits & 0xff;
          
          if (h3 == 64)      enc += String.fromCharCode(o1);
          else if (h4 == 64) enc += String.fromCharCode(o1, o2);
          else               enc += String.fromCharCode(o1, o2, o3);
       } while (i < str.length);
    
       return utf8to16(enc);
    }
    
    function utf16to8(str) {
        var out, i, len, c;
        out = "";
        len = str.length;
        for(i = 0; i < len; i++){
            c = str.charCodeAt(i);
            if ((c >= 0x0001) && (c <= 0x007F)){
                out += str.charAt(i);
            }else if (c > 0x07FF){
                out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
                out += String.fromCharCode(0x80 | ((c >>  6) & 0x3F));
                out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
            }else{
                out += String.fromCharCode(0xC0 | ((c >>  6) & 0x1F));
                out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
            }
        }
        return out;
    }

    function utf8to16(str){
        var out, i, len, c;
        var char2, char3;

        out = "";
        len = str.length;
        i = 0;
        
        while(i < len){
            c = str.charCodeAt(i++);
            switch(c >> 4){ 
                 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                   // 0xxxxxxx
                   out += str.charAt(i-1);
                   break;
                 case 12: case 13:
                   // 110x xxxx   10xx xxxx
                   char2 = str.charCodeAt(i++);
                   out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                   break;
                 case 14:
                   // 1110 xxxx  10xx xxxx  10xx xxxx
                   char2 = str.charCodeAt(i++);
                   char3 = str.charCodeAt(i++);
                   out += String.fromCharCode(((c & 0x0F) << 12) |
                                  ((char2 & 0x3F) << 6) |
                                  ((char3 & 0x3F) << 0));
                  break;
            }
        }
        return out;
    }
    
    // public
    this.encode = encodeBase64;
    this.decode = decodeBase64;
}
/**
UTF8(BOM)  LGPL  trydofor.com  May.2007
===========================================================
String hash(data)
*/

var MD5Class = function()
{
    var MD5_T = new Array(
        0x00000000, 0xd76aa478, 0xe8c7b756, 0x242070db,
        0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613,
        0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1,
        0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e,
        0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51,
        0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681,
        0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87,
        0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9,
        0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
        0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60,
        0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085,
        0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8,
        0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7,
        0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d,
        0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314,
        0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb,
        0xeb86d391
        );

    var MD5_round1 = new Array(
        new Array( 0, 7, 1), new Array( 1,12, 2),
        new Array( 2,17, 3), new Array( 3,22, 4),
        new Array( 4, 7, 5), new Array( 5,12, 6),
        new Array( 6,17, 7), new Array( 7,22, 8),
        new Array( 8, 7, 9), new Array( 9,12,10),
        new Array(10,17,11), new Array(11,22,12),
        new Array(12, 7,13), new Array(13,12,14),
        new Array(14,17,15), new Array(15,22,16)
        );

    var MD5_round2 = new Array(
        new Array( 1, 5,17), new Array( 6, 9,18),
        new Array(11,14,19), new Array( 0,20,20),
        new Array( 5, 5,21), new Array(10, 9,22),
        new Array(15,14,23), new Array( 4,20,24),
        new Array( 9, 5,25), new Array(14, 9,26),
        new Array( 3,14,27), new Array( 8,20,28),
        new Array(13, 5,29), new Array( 2, 9,30),
        new Array( 7,14,31), new Array(12,20,32)
        );

    var MD5_round3 = new Array(
        new Array( 5, 4,33), new Array( 8,11,34),
        new Array(11,16,35), new Array(14,23,36),
        new Array( 1, 4,37), new Array( 4,11,38),
        new Array( 7,16,39), new Array(10,23,40),
        new Array(13, 4,41), new Array( 0,11,42),
        new Array( 3,16,43), new Array( 6,23,44),
        new Array( 9, 4,45), new Array(12,11,46),
        new Array(15,16,47), new Array( 2,23,48)
        );

    var MD5_round4 = new Array(
        new Array( 0, 6,49), new Array( 7,10,50),
        new Array(14,15,51), new Array( 5,21,52),
        new Array(12, 6,53), new Array( 3,10,54),
        new Array(10,15,55), new Array( 1,21,56),
        new Array( 8, 6,57), new Array(15,10,58),
        new Array( 6,15,59), new Array(13,21,60),
        new Array( 4, 6,61), new Array(11,10,62),
        new Array( 2,15,63), new Array( 9,21,64)
        );

    var MD5_round = new Array(
        new Array(MD5_F, MD5_round1),
        new Array(MD5_G, MD5_round2),
        new Array(MD5_H, MD5_round3),
        new Array(MD5_I, MD5_round4)
        );

    function MD5_F(x, y, z) { return (x & y) | (~x & z); }
    function MD5_G(x, y, z) { return (x & z) | (y & ~z); }
    function MD5_H(x, y, z) { return x ^ y ^ z;          }
    function MD5_I(x, y, z) { return y ^ (x | ~z);       }

    function MD5_pack(n32) 
    {
        return  String.fromCharCode(n32 & 0xff) +
                String.fromCharCode((n32 >>> 8) & 0xff) +
                String.fromCharCode((n32 >>> 16) & 0xff) +
                String.fromCharCode((n32 >>> 24) & 0xff);
    }

    function MD5_unpack(s4) 
    {
        return  s4.charCodeAt(0) |
                (s4.charCodeAt(1) <<  8) |
                (s4.charCodeAt(2) << 16) |
                (s4.charCodeAt(3) << 24);
    }

    function MD5_number(n) 
    {
        while (n < 0)
            n += 4294967296;
        while (n > 4294967295)
            n -= 4294967296;
        return n;
    }

    function MD5_apply_round(x, s, f, abcd, r) 
    {
        var a, b, c, d;
        var kk, ss, ii;
        var t, u;

        a = abcd[0];
        b = abcd[1];
        c = abcd[2];
        d = abcd[3];
        kk = r[0];
        ss = r[1];
        ii = r[2];

        u = f(s[b], s[c], s[d]);
        t = s[a] + u + x[kk] + MD5_T[ii];
        t = MD5_number(t);
        t = ((t<<ss) | (t>>>(32-ss)));
        t += s[b];
        s[a] = MD5_number(t);
    }

    function MD5_hash(data) 
    {
        var abcd, x, state, s;
        var len, index, padLen, f, r;
        var i, j, k;
        var tmp;

        state = new Array(0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476);
        len = data.length;
        index = len & 0x3f;
        padLen = (index < 56) ? (56 - index) : (120 - index);
        if(padLen > 0) 
        {
            data += "\x80";
            for(i = 0; i < padLen - 1; i++)
            data += "\x00";
        }
        data += MD5_pack(len * 8);
        data += MD5_pack(0);
        len  += padLen + 8;
        abcd = new Array(0, 1, 2, 3);
        x    = new Array(16);
        s    = new Array(4);

        for(k = 0; k < len; k += 64) 
        {
            for(i = 0, j = k; i < 16; i++, j += 4) 
            {
                x[i] =  data.charCodeAt(j) |
                        (data.charCodeAt(j + 1) <<  8) |
                        (data.charCodeAt(j + 2) << 16) |
                        (data.charCodeAt(j + 3) << 24);
            }
            for(i = 0; i < 4; i++)
                s[i] = state[i];
            for(i = 0; i < 4; i++) 
            {
                f = MD5_round[i][0];
                r = MD5_round[i][1];
                for(j = 0; j < 16; j++) 
                {
                    MD5_apply_round(x, s, f, abcd, r[j]);
                    tmp =   abcd[0];
                            abcd[0] = abcd[3];
                            abcd[3] = abcd[2];
                            abcd[2] = abcd[1];
                            abcd[1] = tmp;
                }
            }

            for(i = 0; i < 4; i++) 
            {
                state[i] += s[i];
                state[i] = MD5_number(state[i]);
            }
        }

        return  MD5_pack(state[0]) +
                MD5_pack(state[1]) +
                MD5_pack(state[2]) +
                MD5_pack(state[3]);
    }

    /* public */
    this.hash = function (data) 
    {
        var i, out, c;
        var bit128;

        bit128 = MD5_hash(data);

        out = "";
        for(i = 0; i < 16; i++) 
        {
            c = bit128.charCodeAt(i);
            out += "0123456789abcdef".charAt((c>>4) & 0xf);
            out += "0123456789abcdef".charAt(c & 0xf);
        }
        return out;
    }
}

/**
UTF8(BOM)  LGPL  trydofor.com  Mar.2008
===========================================================
String hash(data)
*/

var SHA1Class = function()
{
    var charBit = 8;
    
    function sha1_binary(str)
    {
        var w = Array(80);
        var a = 0x67452301;
        var b = 0xefcdab89;
        var c = 0x98badcfe;
        var d = 0x10325476;
        var e = 0xc3d2e1f0;
        var x = strToBigEndianArray(str);
        var strBit = str.length * charBit;
        x[strBit >> 5] |= 0x80 << (24 - (strBit & 0x1f));
        x[((strBit + 64 >> 9) << 4) + 15] = strBit;
        var len = x.length;
        for (var i=0; i<len; i+=16)
        {
            var aa = a, bb = b, cc = c, dd = d, ee = e;
            var j = 0;
            for (; j<16; j++)
            {
                w[j] = x[i + j];
                var t = modularAdd(modularAdd(rotateLeft(a, 5), (b & c) | ((~b) & d)),
                modularAdd(modularAdd(e, w[j]), 0x5A827999));
                e = d;
                d = c;
                c = rotateLeft(b, 30);
                b = a;
                a = t;
            }
            for (; j<20; j++)
            {
                w[j] = rotateLeft(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
                var t = modularAdd(modularAdd(rotateLeft(a, 5), (b & c) | ((~b) & d)),
                modularAdd(modularAdd(e, w[j]), 0x5A827999));
                e = d;
                d = c;
                c = rotateLeft(b, 30);
                b = a;
                a = t;
            }
            for (; j<40; j++)
            {
                w[j] = rotateLeft(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
                var t = modularAdd(modularAdd(rotateLeft(a, 5), b ^ c ^ d),
                modularAdd(modularAdd(e, w[j]), 0x6ED9EBA1));
                e = d;
                d = c;
                c = rotateLeft(b, 30);
                b = a;
                a = t;
            }
            for (; j<60; j++)
            {
                w[j] = rotateLeft(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
                var t = modularAdd(modularAdd(rotateLeft(a, 5), (b & c) | (d & (b | c))),
                modularAdd(modularAdd(e, w[j]), 0x8F1BBCDC));
                e = d;
                d = c;
                c = rotateLeft(b, 30);
                b = a;
                a = t;
            }
            for (; j<80; j++)
            {
                w[j] = rotateLeft(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
                var t = modularAdd(modularAdd(rotateLeft(a, 5), b ^ c ^ d),
                modularAdd(modularAdd(e, w[j]), 0xCA62C1D6));
                e = d;
                d = c;
                c = rotateLeft(b, 30);
                b = a;
                a = t;
            }
            a=modularAdd(a,aa);
            b=modularAdd(b,bb);
            c=modularAdd(c,cc);
            d=modularAdd(d,dd);
            e=modularAdd(e,ee);
        }
        return Array(a, b, c, d, e);
    }
    
    function bigEndianArrayToHex(ar)
    {
        var charHex = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
        var str = "";
        var len = ar.length;
        for(var i = 0, tmp = len << 2; i < tmp; i++)
        {
            str += charHex[((ar[i>>2] >> (((3 - (i & 3)) << 3) + 4)) & 0xF)] +
            charHex[((ar[i>>2] >> ((3 - (i & 3)) << 3)) & 0xF)];
        }
        return str;
    }
    
    function strToBigEndianArray(str)
    {
        var x = Array();
        var mask = (1 << charBit) - 1;
        var len = str.length;
        var i=0;
        for (var j=0; j < len; i+=charBit)
        {
            x[i>>5] |= (str.charCodeAt(j++) & mask) << (32 - charBit - (i & 0x1f));
        }
        return x;
    }
    
    function modularAdd(a, b)
    {    
        var lowerSum = (a & 0xffff) + (b & 0xffff);
        var upperSum = (a >> 16) + (b >> 16) + (lowerSum >> 16);
        return (upperSum << 16) + (lowerSum & 0xffff);
    }
    
    function rotateLeft(val, n)
    {
        return (val << n) | (val >>> (32 - n));
    }
    
    // public
    this.hash = function(str){
        return bigEndianArrayToHex(sha1_binary(str));
    }
}

</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0">
  <tr  height="30">
    <td>
    <input type="button" onclick="md5sum()" value="md5sum" style="background-color:#99CC00"/>
    <input type="button" onclick="sha1sum()" value="sha1sum" style="background-color:#99CC00"/> 
    <input type="button" onclick="enB64()"  value="base64 encode" style="background-color:#CC9900"/> 
    <input type="button" onclick="deB64()"  value="base64 decode" style="background-color:#CC9900"/> 
    <input type="button" onclick="enAes()"  value="aes encrypt" style="background-color:#0066FF"/> 
    <input type="button" onclick="deAes()"  value="aes decrypt" style="background-color:#0066FF"/> 
    </td>
  </tr>
  <tr>
    <td>
        <textarea name="textarea" id="INPUT" style="width:100%; height:100%" ondblclick="this.select()"></textarea>
    </td>
  </tr>
  <tr>
    <td>
        <textarea name="textarea" id="OUTPUT" style="width:100%; height:100%" ondblclick="this.select()"></textarea>
    </td>
  </tr>
</table>

<script type="text/javascript">
var md5Impl  = new MD5Class();
var sha1Impl = new SHA1Class();
var b64Impl  = new B64Class();
var aesImpl  = new AESClass();
var iptObj = document.getElementById("INPUT");
var optObj = document.getElementById("OUTPUT");

function md5sum()
{
    try{
        optObj.value = md5Impl.hash(iptObj.value);
    }catch(e){
        alert("failed to get md5sum:"+e);
    }
}

function sha1sum()
{
    try{
        optObj.value = sha1Impl.hash(iptObj.value);
    }catch(e){
        alert("failed to get sha1sum:"+e);
    }
}

function enB64()
{
    try{
        var ot = b64Impl.encode(iptObj.value);
        optObj.value = format(ot);
    }catch(e){
        alert("failed to get base64 encode:"+e);
    }
}
function deB64()
{
    try{
        optObj.value = b64Impl.decode(iptObj.value.replace(/\s/gm,''));
    }catch(e){
        alert("failed to get base64 decode:"+e);
    }
}
function enAes()
{
    try{
        var passwd = window.prompt('please input your passwd','');
        if(passwd ==null || passwd =='') return;
        
        var ot = b64Impl.encode(aesImpl.encrypt(iptObj.value,passwd,256));
        optObj.value = format(ot);
    }catch(e){
        alert("failed to get base64 encode:"+e);
    }
}
function deAes()
{
    try{
        var passwd = window.prompt('please input your passwd','');
        if(passwd ==null || passwd =='') return;
        
        optObj.value = aesImpl.decrypt(b64Impl.decode(iptObj.value.replace(/\s/gm,'')),passwd,256);
    }catch(e){
        alert("failed to get base64 decode:"+e);
    }
}

function format(text)
{
    if(text == null || text =='') return text;
    
    var linesize = 64;
    
    text = text.replace(/\s+/g,'');
    var rtxt = [];
    for(var i=0;i<text.length;i+=linesize){
        var line = (i+linesize<text.length)?text.substr(i,linesize):text.substr(i);
        rtxt.push(line);
    }
    
    return rtxt.join('\n');
}
</script>
